#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include "led_opr.h"
#include <asm/io.h>


/* GPIO 方向寄存器和数据寄存器 */
static volatile unsigned int *muxctrl_reg85;
static volatile unsigned int *GPIO0_3_DIR;
static volatile unsigned int *GPIO0_3_DATA;

static volatile unsigned int *GPIO0_3_DATAIN;


/* 初始化GPIO方向寄存器和数据寄存器 */
static int board_demo_led_init (int which) 	   
{
	unsigned int val;

	/* GPIO3_? */
    //muxctrl_reg85   = ioremap_nocache(0x120F0000 + 0x058,0x10000);
	//GPIO0_3_DIR     = ioremap_nocache(0x12180000 + 0x400,0x10000);
	//GPIO0_3_DATA    = ioremap_nocache(0x12180000 + 0x3FC,0x10000);
	
	/* GPIO3_6 */
	GPIO0_3_DATAIN  = ioremap_nocache(0x12180000 + 0x100,0x10000);

	//printk("%s %s line %d, led %d\n", __FILE__, __FUNCTION__, __LINE__, which);
	
    /* 1、设置muxctrl_reg85(GPIO0_3)管脚复用寄存器为GPIO功能 */
	//val = *muxctrl_reg85;
	//val &= ~(0xf);
	//*muxctrl_reg85 = val;
		
    /* 2、设置GPIO3_DIR 方向寄存器 */
	//val = *GPIO0_3_DIR;
	//val |= (1<<4);
	//*GPIO0_3_DIR = val;
	
	return 0;
}

/* 控制GPIO引脚 status:1/0 */
static int board_demo_led_ctl (int which, char status)
{
	//printk("%s %s line %d, led %d, %s\n", __FILE__, __FUNCTION__, __LINE__, which, status ? "on" : "off");
	 if(status)
	{
	 	
     /* 3、设置GPIO3_DATA数据寄存器         0：打开 */
		*GPIO0_3_DATA  &= ~(1<<4);
	}
	else 
	{
        /* 4、设置GPIO3_DATA数据寄存器          1：关闭
        * baseaddr 0x1218_0000 offset 0x000～0x3FC
        */
		*GPIO0_3_DATA |= (1<<4);
	}
	
	return 0;
}

static int board_demo_led_read (int which)
{
    return ((*GPIO0_3_DATAIN) &  (1<<6)) ? 1 : 0;
}



/* 自定义驱动设备的结构体 */
static struct led_operations board_demo_led_opr = {
	.num = 1,
	.init = board_demo_led_init, //初始化LED
	.ctl  = board_demo_led_ctl,  //控制LED亮灭
	.read = board_demo_led_read,
};

/* 返回结构体指针 */
struct led_operations *get_board_led_opr(void)
{
	return &board_demo_led_opr;
}


